package com.evil.kingdom.task.timer;

import com.evil.common.mongo.entity.SingleName;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author liyang
 * @date 2024-05-28 15:09
 */
@Slf4j
public abstract class BaseTimerTask<T extends SingleName, C extends BaseTimerTask<T, C, R>, R> extends TimerTask {
    public static final Logger timerTaskLogger = LoggerFactory.getLogger("KINGDOM_TIMER_TASK_LOGGER");

    private final Timer timer;
    @Getter
    private final T t;
    private boolean status;
    @Getter
    private final StopCallback<C> stopCallback;
    @Getter
    private final RunCallback<T, C, R> runCallback;
    private Thread currentThread;

    public BaseTimerTask(Timer timer, T t, StopCallback<C> stopCallback, RunCallback<T, C, R> runCallback) {
        this.timer = timer;
        this.t = t;
        this.status = true;
        this.stopCallback = stopCallback;
        this.runCallback = runCallback;
    }

    @Override
    public void run() {
        this.currentThread = Thread.currentThread();
        if (!this.status) {
            return;
        }
        R result = this.task();
        // 运行回调
        if (null != this.getRunCallback()) {
            this.runCallback.callback(this.t, this.get(), result);
        }
    }

    public abstract R task();

    public abstract C get();

    public void stop() {
        timerTaskLogger.info("{}|stop", this.logPrefix());
        timer.cancel();
        if (null != stopCallback) {
            this.stopCallback.callback(this.get());
        }
        if (null != currentThread) {
            currentThread.interrupt();
        }
    }

    public void pause() {
        timerTaskLogger.info("{}|pause", this.logPrefix());
        this.status = false;
        if (null != currentThread) {
            currentThread.interrupt();
        }
    }

    public void restart() {
        timerTaskLogger.info("{}|restart", this.logPrefix());
        this.status = true;
    }

    public String logPrefix() {
        return String.format("TimerTask|%s|name:%s", this.get().getClass().getSimpleName(), this.t.getName());
    }

    /**
     * 停止回调
     *
     * @param <C> C
     */
    public interface StopCallback<C> {
        void callback(C c);
    }

    /**
     * 运行回调
     *
     * @param <T> T
     * @param <C> C
     */
    public interface RunCallback<T, C, R> {
        void callback(T t, C c, R r);
    }
}
